package com.bsoft.springboot2_7;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.DocumentException;
import com.alibaba.fastjson.JSONObject;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.ObjectUtils;

import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@SpringBootTest
public class test1 {

    private static ObjectMapper mapper = new ObjectMapper();

   /* public static void test(String[] args) {
        try {
            // [文档 2.1] 步骤0: 动态获取公钥
            String publicKeyHex = GmCryptoUtils.getPublicKey(API_URL);
            if (publicKeyHex == null || publicKeyHex.isEmpty()) {
                System.err.println("由于无法获取公钥，程序已终止。");
                return;
            }

            System.out.println("\n--- 1. [文档 3.1] 开始加密流程 ---");

            // [文档 3.1.1] 1. 生成16位密钥种子
            String seedString = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
            // [文档 3.1.1] 2. 将密钥种子转换为32位十六进制 实际SM4密钥
            String actualKeyHex = GmCryptoUtils.stringToHexJsStyle(seedString);

            // [文档 3.1.2] SM2加密临时密钥
            // SM2的明文是上一步生成的 actualKeyHex (32字符的十六进制字符串 实际SM4密钥)
            // 经过调试验证，BouncyCastle的C1C3C2+未压缩模式生成的密文(以04开头)是服务端唯一能正确解密的格式。
            // 因此，文档中“规避04开头密文”的要求已过时或不适用于当前服务端版本，代码中不再需要该循环逻辑。
            String sm2EncryptedKeyHex = GmCryptoUtils.sm2EncryptString(actualKeyHex, publicKeyHex);

            System.out.println("   [+] 使用的密钥种子: " + seedString);
            System.out.println("   [+] 使用的实际SM4密钥: " + actualKeyHex);
            System.out.printf("   [+] SM2加密后的密钥 (未压缩, C1C3C2 格式Hex): %s\n", sm2EncryptedKeyHex);


            // [文档 3.1.3] SM4加密业务数据
            String plainText = gson.toJson(ORIGINAL_PAYLOAD);
            String sm4EncryptedDataHex = GmCryptoUtils.sm4Encrypt(plainText, actualKeyHex);
            System.out.println("   [+] SM4加密后的业务数据 (Hex): " + sm4EncryptedDataHex);

            // [文档 3.1.4] 构造最终请求体
            Map<String, String> finalRequestBodyMap = new HashMap<>();
            // [文档 3.1.4 & 5.1] 特殊的Base64编码：将SM2的十六进制密文直接作为普通字符串进行编码
            String keyBase64 = Base64.getEncoder().encodeToString(sm2EncryptedKeyHex.getBytes(StandardCharsets.UTF_8));
            finalRequestBodyMap.put("key", keyBase64);
            finalRequestBodyMap.put("data", sm4EncryptedDataHex);
            String finalRequestBodyJson = gson.toJson(finalRequestBodyMap);
            System.out.println("   [+] 最终请求体 (Body): " + finalRequestBodyJson);

            // [文档 3.1.5] 构造HTTP头
            String timestamp = String.valueOf(System.currentTimeMillis());
            // [文档 3.1.5 修正] 根据JS Demo，source_string 由 path + 未加密的body构成
            String sourceString = REQUEST_PATH + gson.toJson(ORIGINAL_PAYLOAD);
            String hash = GmCryptoUtils.md5(sourceString);
            String xDataTime = timestamp + hash;

            Headers headers = new Headers.Builder()
                    .add("Content-Type", "application/json")
                    .add("x1-gp-color", "gray")
                    .add("X-Is-Safety", "1")
                    .add("X-Data-Time", xDataTime)
                    .build();
            System.out.println("   [+] 生成的HTTP头: \n" + headers);


            System.out.println("\n--- 2. [文档 3.1] 发送HTTP请求 ---");
            // 构造GET请求，将请求体参数放入URL Query
            HttpUrl.Builder urlBuilder = HttpUrl.parse(API_URL + REQUEST_PATH).newBuilder();
            finalRequestBodyMap.forEach(urlBuilder::addQueryParameter);
            RequestBody body = RequestBody.create(finalRequestBodyJson, MediaType.parse("application/json"));
            Request request = new Request.Builder()
                    .url(API_URL + REQUEST_PATH)
                    .headers(headers)
                    .post(body)
                    .build();

            try (Response response = httpClient.newCall(request).execute()) {
                System.out.println("   [+] 响应状态码: " + response.code());

                String responseXDataTime = response.header("X-Data-Time");
                String responseBodyString = response.body() != null ? response.body().string() : "";

                System.out.println("   [+] 原始响应头 (X-Data-Time): " + responseXDataTime);
                System.out.println("   [+] 原始响应体: " + responseBodyString);

                if (!response.isSuccessful() || responseBodyString.isEmpty() || !"1".equals(response.header("x-is-safety"))) {
                    System.out.println("\n--- 响应非加密或出错，流程结束 ---");
                    return;
                }
                Map<String, Object> responseBodyJson = JSONUtil.toHashMap(responseBodyString);
                if (ObjectUtils.isEmpty(responseBodyJson.get("data"))) {
                    System.out.println("\n--- 响应体中无data字段，流程结束 ---");
                    return;
                }
                String encryptedResponseData = responseBodyJson.get("data").toString();


                System.out.println("\n--- 3. [文档 3.2] 开始解密流程 ---");
                // [文档 3.2.1 & 5.3] 重构SM4密钥
                String reconstructedSeedString = GmCryptoUtils.buildSM4Secret(publicKeyHex, responseXDataTime);
                // [文档 3.2.2] 将重构的密钥种子转换为实际的十六进制密钥
                String reconstructedActualKeyHex = GmCryptoUtils.stringToHexJsStyle(reconstructedSeedString);
                System.out.println("   [+] 重构的密钥种子: " + reconstructedSeedString);
                System.out.println("   [+] 重构的实际SM4密钥: " + reconstructedActualKeyHex);

                // [文档 3.2.2] 解密业务数据
                String decryptedDataString = GmCryptoUtils.sm4Decrypt(encryptedResponseData, reconstructedActualKeyHex);

                System.out.println("\n--- 4. 最终解密结果 ---");
                // 尝试格式化为JSON，如果失败则直接输出字符串
                try {
                    Object parsedJson = gson.fromJson(decryptedDataString, Object.class);
                    System.out.println("最终请求返回解密参数:" + gson.toJson(parsedJson));
                } catch (Exception e) {
                    System.out.println(decryptedDataString);
                }
            }

        } catch (Exception e) {
            System.err.println("\n--- 请求或解密过程中发生错误 ---");
            e.printStackTrace();
        }
    }*/

    public static void main(String[] args) throws Exception {
        String indo = GmCryptoUtils.getMD5Str("510132197610012665");
        Map<String, Object> req = new LinkedHashMap<>(); // Use LinkedHashMap to preserve order
        //req.put("user_id", indo);
        req.put("center_code", "COPD");
        String reqStr = JSONUtil.map2Json(req).toString();

        log.error("明文请求参数:" + reqStr);
        //进入加密流程
        Map<String,Object> resEncBodyDataJson = GmCryptoUtils.commEncrypt(reqStr , "/openapi/v1/fetch-resident-type");
        log.error("解密成功:" + resEncBodyDataJson);

    }

}
